<template>
  <div style="margin-top: 20px">
    <a-tabs v-model:activeKey="activeKey" :type="tabtype" @edit="onEdit" @tabClick="tabClick">
      <a-tab-pane v-for="pane in panes" :key="pane.key" :tab="pane.title" :closable="pane.closable"
        style="background-color: orange"> </a-tab-pane>
      <template #rightExtra>
        <a-upload :showUploadList="false" v-show="true" accept="xlsx" name="file" :headers="headers"
          :customRequest="customRequest">
          <Button type="primary" style="margin-right: 10px;"
            :disabled="boxdata.status == '1' || order >= 1 || tableData.length == 0">导入定位</Button>
        </a-upload>
        <a-button type="primary" :disabled="tableData.length == 0 || isshow.isbutton" @click="confirm(1)">手动核查</a-button>
        <a-button type="primary" :disabled="tableData.length == 0 || isshow.isbutton" @click="confirm(2)"
          style="margin: 0 10px">自动核查</a-button>
        <a-cascader @change="cascaderChange" :disabled="order != 2" placement="bottomRight" :maxTagCount="1"
          v-model:value="cascaderValue" :options="options" :load-data="loadData" placeholder="存储位置" />
      </template>
    </a-tabs>
    <div style="height: 45px; line-height: 45px; display: flex; justify-content: space-around">
      <span> 冻存盒编号: {{ boxdata.serial }} </span>
      <span> 冻存盒类型: {{ boxdata.boxSerial }} </span>
      <span> 冻存盒状态:{{ boxdata.status == 1 ? '已入库' : boxdata.status == 2 ? '待入库' : '空盒' }} </span>
      <span> 冻存盒位置: {{ boxdata.storageDesp }} </span>
      <span> 已存放支数: {{ boxdata.existCount }} </span>
      <span> 剩余孔位数: {{ boxdata.availableCount }} </span>
      <span> 项目组: {{ boxdata.projectNames }} </span>
    </div>
    <div style="display: flex">
      <StorageLocation :tabsortIndex="tabsortIndex" :cols="cols" @rollShow="rollShow" ref="location" :list="tableData"
        :row="row" @endDraggable="endDraggable" :draggable="order == 0"> </StorageLocation>
      <div class="inptable">
        <a-progress v-if="order >= 1" stroke-linecap="square"
          :percent="((notSelected.length - hecha.length) * 100) / notSelected.length" :strokeWidth="10" :show-info="false"
          trailColor="#ccc" :stroke-color="{ from: '#108ee9', to: '#87d068' }" status="active" />
        <vxe-table align="center" border ref="vxeTable123" :row-config="{ isCurrent: true, isHover: true, height: 35 }"
          :data="tableData" max-height="375px" show-overflow>
          <vxe-column title="位置" width="70px">
            <template #default="{ row }">
              {{ row.seat }}
            </template>
          </vxe-column>
          <vxe-column field="originalSerial" title="样本编号"></vxe-column>
          <vxe-column field="name" title="样本名称"></vxe-column>
          <vxe-column field="sampleTime" title="采样日期" width="170px">
            <template #default="{ row }">
              {{ row.sampleTime.substring(0, 10) }}
            </template>
          </vxe-column>
          <vxe-column field="serial" title="数字编号"></vxe-column>
          <vxe-column field="newcapacity" title="容量" width="70px"></vxe-column>
          <vxe-column field="status" title="核查" width="70px" style="text-align: center">
            <template #default="{ row }">
              <svg v-if="row.status == 2" t="1680592527152" class="icon" viewBox="0 0 1024 1024" version="1.1"
                xmlns="http://www.w3.org/2000/svg" p-id="2909" width="45" height="20">
                <path
                  d="M512.024381 0C229.205333 0 0 229.205333 0 512.024381 0 794.770286 229.205333 1024 512.024381 1024 794.770286 1024 1024 794.770286 1024 512.024381 1024 229.205333 794.770286 0 512.024381 0M849.603048 353.328762l-385.462857 385.462857c-9.411048 9.411048-21.723429 14.09219-34.06019 14.09219s-24.697905-4.681143-34.084571-14.09219l-221.622857-221.647238c-18.822095-18.822095-18.822095-49.322667 0-68.120381 18.822095-18.846476 49.322667-18.846476 68.144762 0l187.562667 187.562667 351.378286-351.402667c18.822095-18.822095 49.322667-18.822095 68.144762 0C868.425143 304.006095 868.425143 334.506667 849.603048 353.328762"
                  fill="#5bdc9c" p-id="2910" data-spm-anchor-id="a313x.7781069.0.i0" class=""></path>
              </svg>
              <svg v-else t="1680592590083" class="icon" viewBox="0 0 1024 1024" version="1.1"
                xmlns="http://www.w3.org/2000/svg" p-id="3923" width="45" height="20">
                <path
                  d="M512 981.333333C252.8 981.333333 42.666667 771.2 42.666667 512S252.8 42.666667 512 42.666667s469.333333 210.133333 469.333333 469.333333-210.133333 469.333333-469.333333 469.333333z m44.245333-469.333333l159.914667-159.914667a31.274667 31.274667 0 1 0-44.245333-44.245333L512 467.754667 352.085333 307.84a31.274667 31.274667 0 1 0-44.245333 44.245333L467.754667 512l-159.914667 159.914667a31.274667 31.274667 0 1 0 44.245333 44.245333L512 556.245333l159.914667 159.914667a31.274667 31.274667 0 1 0 44.245333-44.245333L556.245333 512z"
                  fill="#F5222D" p-id="3924"></path>
              </svg>
            </template>
          </vxe-column>
          <vxe-column field="sampleAddress" title="操作">
            <template #default="{ row }">
              <vxe-button status="primary" @click="deleteSample(row)" size="mini"
                :disabled="order > 0 || (row?.strainIndex >= 0 && boxdata.status != 2)">移除</vxe-button>
            </template>
          </vxe-column>
        </vxe-table>
      </div>
    </div>
  </div>
  <!-- 详情抽屉 -->
  <specificsDmodal :options="options" ref="specifics" @submitData="submitData"></specificsDmodal>
  <confirmReceipt :manageLinkList="manageLinkList" @submitData="voluntarily" :id="formNo" :tableData="panes.value"
    ref="double"></confirmReceipt>
</template>
<script setup lang="ts">
import { ref, reactive, defineExpose, defineEmits, watch, onBeforeUnmount } from 'vue';
import StorageLocation from '@/components/StorageLocation.vue';
import { billIn, inputUpdate, storageTree, inputGetById } from '../../../api/input_manage';
import { subscript } from '@/libs/utils';
import { positionImport, postCheck } from '@/api/utils';
import { searchDevice, deviceQuery } from '@/api/emq-openapi';
import specificsDmodal from './specifics.vue';
import confirmReceipt from './confirmReceipt.vue';
import MQTT from '@/framework/utils/mqtt';
import { message, Button } from 'ant-design-vue';
import { useRoute, useRouter } from 'vue-router';
const route = useRoute();
const router = useRouter();
const double = ref();
//入库步骤 0 什么都没有  1 开始核查  2 选择储位  3 底单存档   4完成
const order = ref(0);
const props = defineProps({
  formNo: { type: String, default: '' },
  formTime: { type: String, default: '' },
  manageLinkList: { type: Array, default: [] },
});
const isshow = ref({
  isbutton: false,
});
const tabtype = ref('editable-card');
const specifics = ref();
const submitData = (data) => {
  data.forEach((el) => {
    if (panes.value && !panes.value.some((item) => item.id == el.id)) add(el);
  });
  specifics.value.visible = false;
};
const disabledTree = (data) => {
  data.forEach((item) => {
    if (item.children.length > 0) {
      disabledTree(item.children);
    } else {
      item.disabled = item.availableCapacity != item.capacity;
    }
  });
};

// 储存位置选择
const options = ref([]);
const getTree = (async () => {
  const { result } = await storageTree();
  if (route.query.id) {
    let arr = result.filter(item => item.name != '中转区')
    disabledTree(arr);
    options.value = arr
  } else {
    options.value = result;
  }
})();

watch(() => order.value, () => {
  if (order.value == 2) {
    options.value = options.value.filter(item => item.name != '中转区')
    disabledTree(options.value);
  }
})
let recursion = (arr, tree) => {
  tree.forEach((item) => {
    if (item.children.length > 0) {
      recursion(arr, item.children);
    } else {
      item.disabled = item.availableCapacity != item.capacity || arr.includes(item.id);
    }
  });
};
// tab切换的时候存储位置显示变化
const cascaderChange = (value, selectedOptions) => {
  let str = '';
  let panesObj = panes.value.find((item) => item.id == activeKey.value);
  if (!selectedOptions) return (panesObj.serial = '');
  selectedOptions.forEach((item) => {
    str == '' ? (str += item.name) : (str += `-${item.name}`);
  });
  panesObj.storageDesp = str;
  panesObj.serialId = selectedOptions[selectedOptions.length - 1].id;
  panesObj.deviceId = selectedOptions[selectedOptions.length - 1].deviceId;
  let arr = panes.value.map((item) => item.serialId);
  recursion(arr, options.value);
};
const rollShow = (row) => {
  vxeTable123.value.scrollToRow(vxeTable123.value.getData(row));
  vxeTable123.value.setCurrentRow(tableData.value[row]);
};
const cascaderValue: any = ref([]);
const loadData = () => { };

const emit = defineEmits(['removeAdd', 'depositing', 'fomeDataId', 'authority', 'deltabData']);
const vxeTable123 = ref();
const vxeTableModal = ref();
const boxdata = ref({
  storageDesp: '',
  boxSerial: '',
  status: '',
  existCount: 0,
  availableCount: 0,
  serial: '',
  projectNames: '',
  epc: ''
});
const tableData: any = ref([]);
const location = ref();
// 盒子信息
const panes: any = ref([]);
//tabs标签id
const activeKey = ref(panes.value[0]?.key);
// tabs切换的数据
const sampleBox = ref();
watch(
  () => activeKey.value,
  (val, prevVal) => {
    sampleBox.value = panes?.value.find((item) => item.id == activeKey.value);
    sampleBox.value.closable = true;
    isshow.value.isbutton = tableData.value.every((item) => item.status == 2) && tableData.value.length > 0;
    tabClick(activeKey.value);
    getNewCheck();
  },
);
const notSelected = ref([]);
const hecha = ref([]);
watch(
  () => tableData.value.length,
  (val, prevVal) => {
    notSelected.value = [];
    notSelected.value = tableData.value.filter((item) => !item.batchId);
    okhecha();
  },
);
const okhecha = () => {
  hecha.value = notSelected.value.filter((item) => item.status != 2);
};
// 单据数据
const check: any = reactive({
  equipmentSow: [],
  subSpecimens: [],
  check: '',
  id: '',
  boxsn: ''
});
const row = ref(10);
const cols = ref(10);
// 拖拽事件结束回调
const endDraggable = (arr) => {
  tableData.value.forEach((item) => {
    if (item.sortIndex == arr[0]) {
      item.sortIndex = arr[1];
      item.seat = subscript(arr[1], row.value);
    } else if (item.sortIndex == arr[1]) {
      item.sortIndex = arr[0];
      item.seat = subscript(arr[0], row.value);
    }
  });
};
//tabs添加
const add = (data) => {
  activeKey.value = data.id;
  panes.value.forEach((item) => (item.closable = false));
  panes.value.push({
    title: data.serial,
    key: activeKey.value,
    list: data.tableData,
    ...data,
    submitStatus: data.submitStatus ? data.submitStatus : 0,
    serialId: data.storageId ? data.storageId : '',
  });
  cascaderValue.value[0] = data?.storageDesp ? data?.storageDesp : '';
  boxchange(panes.value[panes.value.length - 1]);
  row.value = data.rows;
  cols.value = data.cols;
  if (tableData.value) {
    getNewCheck();
  }
};
//tabs删除
const remove = (targetKey: string) => {

  let lastIndex = 0;
  panes.value.forEach((pane, i) => {
    if (pane.key === targetKey) {
      lastIndex = i - 1;
    }
  });
  panes.value = panes.value.filter((pane) => pane.key !== targetKey);
  emit('deltabData')
  if (panes.value.length && activeKey.value === targetKey) {
    if (lastIndex >= 0) {
      activeKey.value = panes.value[lastIndex].key;
    } else {
      activeKey.value = panes.value[0].key;
    }
  } else {
    resetInput();
  }
};
// 页面数据初始化
const resetInput = () => {
  panes.value = [];
  order.value = 0;
  tableData.value = [];
  boxdata.value = {
    storageDesp: '',
    boxSerial: '',
    status: '',
    existCount: 0,
    availableCount: 0,
    serial: '',
    projectNames: '',
    epc: ''
  };
  tabtype.value = 'editable-card';
};
// 盒子信息展示/
const boxchange = (item) => {
  boxdata.value.storageDesp = item.storageDesp;
  boxdata.value.serial = item.serial;
  boxdata.value.boxSerial = item.boxSerial;
  boxdata.value.status = item.status;
  boxdata.value.existCount = item.existCount;
  boxdata.value.availableCount = item.availableCount;
  boxdata.value.epc = item.epc;
  tableData.value = item.list;
  boxdata.value.projectNames = item.projectNames;
};
const onEdit = (targetKey: string | MouseEvent, action: string) => {
  if (action === 'add') {
    specifics.value.visible = true;
  } else {
    remove(targetKey as string);
  }
};
// tabs切换
const tabClick = (num) => {
  if (num == activeKey) return;
  activeKey.value = num;
  panes.value.forEach((item) => {
    if (item.id != num) {
      item.closable = false;
    } else {
      row.value = item.rows
      cols.value = item.cols
      boxchange(item);
      vxeTable123.value.loadData(tableData.value);
      item?.storageDesp ? (cascaderValue.value[0] = item?.storageDesp) : (cascaderValue.value = []);
    }
  });
};
//把上面的选择的数据塞进下面表格
const linkage = (arr) => {
  let panesObj = panes.value.find((item) => item.id == activeKey.value);
  arr.forEach((item) => {
    let sortIndex = panesObj.list.map((item) => item.sortIndex);
    for (let i = 0; i < 500; i++) {
      if (sortIndex.every((ul) => ul != i)) item.sortIndex = i;
      if (item.sortIndex > 0 || item.sortIndex == 0) {
        item.seat = subscript(item.sortIndex, row.value);
        break;
      }
    }
    panesObj.list.unshift(item);
  });
  tableData.value = panesObj.list
  vxeTable123.value.loadData(tableData.value);
};
//移除事件
const deleteSample = (row) => {
  let num = tableData.value.findIndex((item) => item.id == row.id)
  tableData.value[num].sortIndex = null
  tableData.value.splice(num, 1);
  vxeTable123.value.remove(row);
  emit('removeAdd', row);
};
//处理提交的样本和盒子数据结构
const boxData = (data) => {
  return data.map((item) => {
    item.list.forEach(el => el.extDataList = [])
    return {
      epcId: item.id,
      wholeBox: item.status == 1 ? 0 : 1,
      subSpecimens: item.list,
    }

  });
};
// 获取数据回显
const EchoInput = async (id) => {
  const { result } = await inputGetById(id);
  result.stocks.forEach((item) => {
    item.subSpecimens.forEach((el) => {
      el.seat = subscript(el.sortIndex, item.boxRows);
      el.newcapacity = el.capacity + (el.unit == 1 ? 'ml' : 'μl')
    });
  });
  emit('authority', result.stocks);
  check.id = id;

  if (result.billStatus >= 0) emit('depositing');
  emit('fomeDataId', [result.batchNo, result.cautionTime]);

  order.value = result.status;
  if (order.value >= 1) tabtype.value = 'card';
  result.stocks.forEach((item) => {
    add({
      id: item.epcId,
      boxSerial: item.serial,
      tableData: item.subSpecimens,
      ...item,
    });
  });
};
if (route.query.id) {
  // 获取数据回显
  EchoInput(route.query.id);
}
const confirm = (num) => {
  double.value.onOpen(num, panes.value);
};
//核查按钮点击事件
const voluntarily = async (data) => {
  let billData = {
    status: 1,
    memo: '',
    batchNo: props.formNo,
    operatorName: data[1],
    systemId: 0,
    stocks: boxData(panes.value),
    cautionTime: props.formTime
  };
  tabtype.value = 'card';
  order.value = 1;
  if (!check.id) {
    let { result } = await billIn(billData);
    check.id = result;
  }
  emit('authority', panes.value);
  if (data[0] == 2) {
    NumberEquipment('BOX');
  } else {
    manmade();
  }
};

//手动核查
const manmade = (bol = false) => {
  let arr = [];
  panes.value.forEach((item) => {
    if (item.list) {
      item.list.forEach((el) => {
        el.status = 2;
      });
    }
    if (item.subSpecimens) {
      item.subSpecimens.forEach((el) => {
        el.status = 2;
      });
    }
    arr.push({ epcId: item.id, subSpecimens: item.list ? item.list : item.subSpecimens, submitStatus: 2 });
  });
  bol ? setdata(arr, bol) : setdata(arr, bol);
  okhecha();
};
const getNewCheck = () => {
  check.subSpecimens = tableData.value
    .filter((item) => item.status != 2)
    .map((item, i) => ({
      num: i + 1,
      epc: item.epc,
      submitStatus: item.submitStatus === 2 ? '已核查' : '未核查',
      originalSerial: item.originalSerial,
      name: item.name,
      serial: item.serial,
    }));
};
const setdata = async (arr, bol) => {
  const { result } = await inputUpdate({
    status: 1,
    id: check.id,
    stocks: arr,
  });
  if (bol) {
    let arr: any = []
    panes.value.forEach(item => {
      let subSpecimens = item.list ? item.list : item.subSpecimens
      arr.push(...subSpecimens)
    })
    const postdata = { "name": check.boxsn, "deviceType": 41, "useType": 2, "count": arr.length + '支', "parentId": check.id }
    postCheck(postdata)
  }
  MQTT.publish("bims/box/" + check.boxsn + "/check", '{"on":false}');
  isshow.value.isbutton = true;
  sampleBox.value.submitStatus = 2;
  if (result == 2) {
    order.value = 2;
    disabledTree(options.value);
  }
};
//自动核查
const verification: any = ref([]);
const NumberEquipment = async (type) => {
  verification.value = [];
  let { data } = await searchDevice([]);
  let devices = data.filter((item) => item.connected && item.clientid && item.clientid.startsWith(type));
  if (devices.length === 0) {
    check.equipmentSow = [];
    return message.warning('未检测到交接仓');
  } else if (devices.length === 1) {
    check.equipmentSow = [{ sn: devices[0].clientid.split('_')[1] }];
  } else {
    let paging = {
      pageNum: 1,
      pageSize: 999999,
      'orderBy[0].field': 'createTime',
      'orderBy[0].order': 'desc',
    };
    let res = await deviceQuery(paging);
    devices.forEach((el) => {
      let str = el.clientid.split('_')[1];
      res.data.result.data.forEach((ul) => {
        if (ul.sn == str) check.equipmentSow.push({ name: ul.name, sn: str });
      });
    });
  }
  let arr: any = [];
  panes.value.forEach((el) => {
    let data = el.list ? el.list : el.subSpecimens;
    data.forEach((item, i) => {
      item.batchId ? (item.submitStatus = 2) : '';
      verification.value.push(item);
      arr.push({
        num: i + 1,
        epc: item.epc,
        submitStatus: item.submitStatus === 2 ? '已核查' : '未核查',
        originalSerial: item.originalSerial,
        name: item.name,
        serial: item.serial,
      });
    });
  });
  let taskInfo = {
    on: true,
    taskList: { taskType: 'IN', taskinfo: props.formNo, taskDetail: arr },
  };
  check.boxsn = check.equipmentSow[0].sn
  MQTT.publish('bims/box/' + `${check.equipmentSow[0].sn}` + '/check', JSON.stringify(taskInfo));
  MQTT.subscribe('bims/box/' + `${check.equipmentSow[0].sn}` + '/check/tagReport', 0);
  MQTT.$on('mqtt-msg', (res) => {
    if (router.currentRoute.value.name == 'input_manage_detail' || router.currentRoute.value.name == 'input_manage') {
      let obj = JSON.parse(res.msg.toString());
      obj.tags.forEach((item) => {
        verification.value.forEach((el) => {
          if (el.epc == item.epc) {
            el.status = 2;
          }
        });
        check.subSpecimens = tableData.value.filter((item) => item.status != 2);
        if (!verification.value.some((al) => al.status != 2)) manmade(true);
        vxeTableModal.value?.loadData(check.subSpecimens);
      });
    }
  });
};
//导入定位部分
const headers = {
  authorization: 'authorization-text',
};
const tabsortIndex = ref()
// 文件上传点击事件
const customRequest = async (e) => {
  let data = new FormData();
  data.append('file', e.file); //如果还有其他参数复制就行了
  const { result } = await positionImport(data);
  let res = result[0]
  if (res?.boxInstance.epc != boxdata.value.epc) return message.warning('导入文件中epc编号与当前盒子信息不符，请重新导入')
  if (res?.strainInstanceDetails.length != tableData.value.length) return message.warning('导入文件中样本数量与当前已选样本数量不一致，请重新导入')
  for (let i = 0; i < tableData.value.length; i++) {
    let item = tableData.value[i]
    if (!res.strainInstanceDetails.find((element) => element.epc == item.epc)) return message.warning(`样本: ${item.epc}未包含在导入文件中，请重新导入`)
  }
  message.success('导入定位成功')
  tableData.value.forEach((item, index) => {
    item.sortIndex = res?.strainInstanceDetails[index].strainIndex
    item.seat = subscript(item.sortIndex, row.value);
  });
  tabsortIndex.value = tableData.value.map(item => item.sortIndex)
};
onBeforeUnmount(() => {
  MQTT.publish("bims/box/" + check.boxsn + "/check", '{"on":false}');
  MQTT.unsubscribe("bims/box/" + check.boxsn + "/check/tagReport");
});
defineExpose({
  panes,
  linkage,
  order,
  check,
  resetInput,
});
</script>
<style lang="less" scoped>
::v-deep .ant-tabs-card.ant-tabs-top>.ant-tabs-nav .ant-tabs-tab-active {
  background-color: #83bcf9;
  border-radius: 7px 7px 0 0;
  padding: 0px 25px;
  height: 32px;
}

::v-deep .ant-tabs-card>.ant-tabs-nav .ant-tabs-tab {
  border-radius: 7px 7px 0 0;
  padding: 0px 25px;
  height: 32px;
  background-color: #efefef;
}

::v-deep .ant-tabs-nav-wrap {
  height: 32px;
}

::v-deep .ant-tabs>.ant-tabs-nav .ant-tabs-nav-list {
  align-items: center;
}

::v-deep .ant-tabs>.ant-tabs-nav .ant-tabs-nav-add {
  color: #67acf7;
  border-radius: 12px;
  border: 1px solid #67acf7;
  min-width: 24px;
  width: 24px;
  height: 24px;
  padding: 0;
}

::v-deep .ant-card-head {
  display: none;
}

::v-deep .ant-card-body {
  padding: 0;
  padding-bottom: 0;
}

::v-deep .table-search {
  margin-bottom: 0;
  padding-top: 0;
}

::v-deep .ant-modal-footer {
  display: none;
  padding: 0;
}

.inptable {
  flex: 1;
  margin-left: 20px;
}

.inventory {
  border: 1px solid #ccc;
  height: 85%;
  width: 100%;
  overflow: auto;
}
</style>
